package com.hddz.comlib;

import java.util.HashMap;

import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;

public class GlobleSettings {
	// These settings are stored in SharedPreferences
	private static String SHARED_PREFERENCES_NAME = "com.hddz.comlib"; //$NON-NLS-1$

	// / Settings variables
	private Application ctx;
	private SharedPreferences globalPreferences;
	private SharedPreferences defaultProfilePreferences;
	private SharedPreferences profilePreferences;

	private static HashMap<String, String> globalConfig = new HashMap<String, String>();

	private static GlobleSettings INSTANCE;

	public static GlobleSettings getGlobleSettings(Context ctx) {
		if (INSTANCE == null) {
			synchronized (ctx.getApplicationContext()) {
				if (INSTANCE == null) {
					INSTANCE = new GlobleSettings((Application) ctx.getApplicationContext());
				}
			}
		}
		return INSTANCE;
	}

	public interface OsmandPreference<T> {
		T get();

		boolean set(T obj);

		String getId();
	}

	private GlobleSettings(Application ctx) {
		this.ctx = ctx;
		profilePreferences = defaultProfilePreferences = globalPreferences = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE);
	}

	public static String getConfigValue(String key) {
		synchronized (globalConfig) {
			if (globalConfig != null && globalConfig.containsKey(key)) {
				return globalConfig.get(key);
			} else {
				return key;
			}
		}
	}

	public static void putConfigValue(String key, String value) {
		synchronized (globalConfig) {
			if (!globalConfig.containsKey(key)) {
				globalConfig.put(key, value);
			} else {
				globalConfig.remove(key);
				globalConfig.put(key, value);
			}
		}
	}

	private SharedPreferences getProfilePreferences() {
		return ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE);
	}

	public abstract class CommonPreference<T> implements OsmandPreference<T> {
		private final String id;
		private final boolean global;
		private T cachedValue;
		private SharedPreferences cachedPreference;
		private boolean cache;
		private T defaultValue;

		public CommonPreference(String id, boolean global, T defaultValue) {
			this.id = id;
			this.global = global;
			this.defaultValue = defaultValue;
		}

		public CommonPreference(String id, boolean global, boolean cache, T defaultValue) {
			this.id = id;
			this.global = global;
			this.cache = cache;
			this.defaultValue = defaultValue;
		}

		protected SharedPreferences getPreferences() {
			return global ? globalPreferences : profilePreferences;
		}

		protected T getDefaultValue() {
			if (global) {
				return defaultValue;
			}
			if (defaultProfilePreferences.contains(getId())) {
				return getValue(defaultProfilePreferences, defaultValue);
			} else {
				return defaultValue;
			}
		}

		protected abstract T getValue(SharedPreferences prefs, T defaultValue);

		protected abstract boolean setValue(SharedPreferences prefs, T val);

		@Override
		public T get() {
			if (cache && cachedValue != null && cachedPreference == getPreferences()) {
				return cachedValue;
			}
			cachedPreference = getPreferences();
			cachedValue = getValue(cachedPreference, getDefaultValue());
			return cachedValue;
		}

		@Override
		public String getId() {
			return id;
		}

		@Override
		public boolean set(T obj) {
			SharedPreferences prefs = getPreferences();
			if (setValue(prefs, obj)) {
				cachedValue = obj;
				cachedPreference = prefs;
				return true;
			}
			return false;
		}

	}

	private class BooleanPreference extends CommonPreference<Boolean> {

		private BooleanPreference(String id, boolean defaultValue, boolean global) {
			super(id, global, defaultValue);
		}

		private BooleanPreference(String id, boolean defaultValue, boolean global, boolean cache) {
			super(id, global, cache);
		}

		@Override
		protected Boolean getValue(SharedPreferences prefs, Boolean defaultValue) {
			return prefs.getBoolean(getId(), defaultValue);
		}

		@Override
		protected boolean setValue(SharedPreferences prefs, Boolean val) {
			return prefs.edit().putBoolean(getId(), val).commit();
		}

	}

	private class IntPreference extends CommonPreference<Integer> {

		private IntPreference(String id, int defaultValue, boolean global) {
			super(id, global, defaultValue);
		}

		private IntPreference(String id, int defaultValue, boolean global, boolean cache) {
			super(id, global, cache, defaultValue);
		}

		@Override
		protected Integer getValue(SharedPreferences prefs, Integer defaultValue) {
			return prefs.getInt(getId(), defaultValue);
		}

		@Override
		protected boolean setValue(SharedPreferences prefs, Integer val) {
			return prefs.edit().putInt(getId(), val).commit();
		}

	}

	private class StringPreference extends CommonPreference<String> {

		private StringPreference(String id, String defaultValue, boolean global) {
			super(id, global, defaultValue);
		}

		@Override
		protected String getValue(SharedPreferences prefs, String defaultValue) {
			return prefs.getString(getId(), defaultValue);
		}

		@Override
		protected boolean setValue(SharedPreferences prefs, String val) {
			return prefs.edit().putString(getId(), val).commit();
		}

	}

	private class EnumIntPreference<E extends Enum<E>> extends CommonPreference<E> {

		private final E[] values;

		private EnumIntPreference(String id, E defaultValue, boolean global, boolean cache, E[] values) {
			super(id, global, cache, defaultValue);
			this.values = values;
		}

		private EnumIntPreference(String id, E defaultValue, boolean global, E[] values) {
			super(id, global, defaultValue);
			this.values = values;
		}

		@Override
		protected E getValue(SharedPreferences prefs, E defaultValue) {
			int i = prefs.getInt(getId(), -1);
			if (i < 0 || i >= values.length) {
				return defaultValue;
			}
			return values[i];
		}

		@Override
		protected boolean setValue(SharedPreferences prefs, E val) {
			return prefs.edit().putInt(getId(), val.ordinal()).commit();
		}

	}

	public CommonPreference<String> START_DATE = new StringPreference("start_date", "", true);
	
	public CommonPreference<String> END_DATE = new StringPreference("end_date", "", true);
	
	public CommonPreference<String> INTERVAL = new StringPreference("interval", "", true);
	
	public CommonPreference<Integer> MAP_LAST_LAT = new IntPreference("map_last_lat", 30, true);

	public CommonPreference<Integer> MAP_LAST_LON = new IntPreference("map_last_lon", 120, true);

	public CommonPreference<String> READ_INTERVAL = new StringPreference("read_interval", "1分钟", true);

	public CommonPreference<String> SEARCH_CODITION = new StringPreference("search_conditio", "username", true);

	public CommonPreference<Integer> STATION_GPS_FLAG = new IntPreference("station_gps_flag", 200, true);

	public CommonPreference<Integer> STATION_HISTROY_READ_ITEM_VALUE_1 = new IntPreference("station_histroy_read_item_value_1", R.id.rb_station_item_sjchannel, true);

	public CommonPreference<Integer> STATION_HISTROY_READ_ITEM_VALUE_2 = new IntPreference("station_histroy_read_item_value_2", R.id.rb_station_item_fxchanel, true);

	public CommonPreference<Integer> STATION_DETAIL_HISTROY_READ_ITEM_VALUE_1 = new IntPreference("station_detail_histroy_read_item_value_1", R.id.rb_station_item_sjchannel, true);

	public CommonPreference<Integer> STATION_DETAIL_HISTROY_READ_ITEM_VALUE_2 = new IntPreference("station_detail_histroy_read_item_value_2", R.id.rb_station_item_zxchanel, true);

	public CommonPreference<String> BLUETOOTH_DEVICE_ADDRESS = new StringPreference("bluetooth_device_address", "", true);

	public CommonPreference<Integer> STATION_UNINPUTED_ONE = new IntPreference("station_uninputed_one", R.id.rb_station_item_username, true);

	public CommonPreference<Integer> STATION_UNINPUTED_TWO = new IntPreference("station_uninputed_two", R.id.rb_station_item_watermeterbodyno, true);

	public CommonPreference<Integer> STATION_UNINPUTED_THREE = new IntPreference("station_uninputed_three", R.id.rb_station_item_pertime, true);

	public CommonPreference<Integer> STATION_INPUTED_ONE = new IntPreference("station_inputed_one", R.id.rb_station_item_username, true);

	public CommonPreference<Integer> STATION_INPUTED_TWO = new IntPreference("station_inputed_two", R.id.rb_station_item_userno, true);

	public CommonPreference<Integer> STATION_INPUTED_THREE = new IntPreference("station_inputed_three", R.id.rb_station_item_lasttime, true);

	public CommonPreference<Integer> STATION_INPUT_SEARCH_ITEM_ONE = new IntPreference("station_input_search_item_one", R.id.rb_station_item_username, true);

	public CommonPreference<Integer> STATION_INPUT_SEARCH_ITEM_TWO = new IntPreference("station_input_search_item_two", R.id.rb_station_item_watermeterbodyno, true);

	public CommonPreference<Integer> STATION_INPUT_SEARCH_ITEM_THREE = new IntPreference("station_input_search_item_three", R.id.rb_station_item_state, true);

	public CommonPreference<Integer> STATION_GPS_STATUS_ITEM_ONE = new IntPreference("station_gps_status_item_one", R.id.rb_station_item_username, true);

	public CommonPreference<Integer> STATION_GPS_STATUS_ITEM_TWO = new IntPreference("station_gps_status_item_two", R.id.rb_station_item_watermeterbodyno, true);

	public CommonPreference<Integer> STATION_GPS_STATUS_ITEM_THREE = new IntPreference("station_gps_status_item_three", R.id.rb_station_item_gps_state, true);

	public CommonPreference<Integer> STATION_SEARCH_ONE = new IntPreference("station_search_one", R.id.rb_station_item_username, true);

	public CommonPreference<Integer> STATION_SEARCH_TWO = new IntPreference("station_search_two", R.id.rb_station_item_watermeterbodyno, true);

	public CommonPreference<Integer> STATION_SEARCH_THREE = new IntPreference("station_search_three", R.id.rb_station_item_state, true);

	public CommonPreference<Integer> STATION_SCAN_ONE = new IntPreference("station_scan_one", R.id.rb_station_item_stationno, true);

	public CommonPreference<Integer> STATION_SCAN_TWO = new IntPreference("station_scan_two", R.id.rb_station_item_time, true);

	public CommonPreference<Integer> STATION_NEAR_ONE = new IntPreference("station_near_one", R.id.rb_station_item_stationno, true);

	public CommonPreference<Integer> STATION_NEAR_TWO = new IntPreference("station_near_two", R.id.rb_station_item_voltage, true);

	public CommonPreference<Integer> STATION_NEAR_THREE = new IntPreference("station_near_three", R.id.rb_station_item_time, true);

}
